﻿// CTabControl.cpp: 实现文件
//

#include "pch.h"
#include "DntDemo.h"
#include "afxdialogex.h"
#include "CTabControl.h"
#include "TxtUtils.h"
#include "DiffBkTx.h"
#include "DntTest.h"
#define TAG	"TabControl"


// CTabControl 对话框

IMPLEMENT_DYNAMIC(CTabControl, CDialogEx)

CTabControl::CTabControl(CWnd* pParent /*=nullptr*/)
	: CDialogEx(IDD_TAB_CONTROL, pParent){
}

CTabControl::~CTabControl(){
}

void CTabControl::DoDataExchange(CDataExchange* pDX){
	CDialogEx::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CTabControl, CDialogEx)
	ON_WM_TIMER()
	ON_NOTIFY(NM_CUSTOMDRAW, IDC_SLIDER1, &CTabControl::OnNMCustomdrawSlider1)
	ON_BN_CLICKED(IDC_BUTTON_RANDOM, &CTabControl::OnBnClickedButtonRandom)
	ON_BN_CLICKED(IDC_BUTTON_LOGIN, &CTabControl::OnBnClickedButtonLogin)
	ON_BN_CLICKED(IDC_BUTTON_CHANGE, &CTabControl::OnBnClickedButtonChange)
	ON_EN_CHANGE(IDC_EDIT_REG_ADDR, &CTabControl::OnEnChangeEditReg)
	ON_EN_SETFOCUS(IDC_EDIT_REG_ADDR, &CTabControl::OnEnChangeEditReg)
	ON_EN_CHANGE(IDC_EDIT_REG_DATA, &CTabControl::OnEnChangeEditReg)
	ON_EN_SETFOCUS(IDC_EDIT_REG_DATA, &CTabControl::OnEnChangeEditReg)
END_MESSAGE_MAP()


// CTabControl 消息处理程序

extern CTabControl* mTabControl;
static bool isChangReg;
static int gChangEdit;
static int gRegAddr;
static void changRegCallback() {
	if (mTabControl != NULL) {
		mTabControl->ShowRegister();
	}
}
extern "C" static void loginOkCallback() {
	if (mTabControl != NULL) {
		mTabControl->ShowRegister();
	}
}

BOOL CTabControl::OnInitDialog(){
	CDialogEx::OnInitDialog();

	// TODO:  在此添加额外的初始化
	isChangReg = false;
	gChangEdit = 0;

	ShowAccount(true);

	TestChangRegCallback(changRegCallback);
	TestLoginOkCallback(loginOkCallback);
	SetTimer(1, 300, NULL);

	gRegAddr = DbsGetMemValue("regAddr");
	SetEditHexValue(IDC_EDIT_REG_ADDR, gRegAddr, true);		// 写入HEX数值到CEdit
	ShowRegister();
	((CSliderCtrl*)GetDlgItem(IDC_SLIDER1))->SetRange(0, 255);
	srand((int)GetTickCount64());
	return TRUE;  // return TRUE unless you set the focus to a control
	// 异常: OCX 属性页应返回 FALSE
}


void CTabControl::OnTimer(UINT_PTR nIDEvent){
	CDialogEx::OnTimer(nIDEvent);
	if (isChangReg) {
		isChangReg = false;
		ShowRegister();
	}
	if (gChangEdit > 0 && ++gChangEdit > 6) {						// 在编辑内容被改变约2秒后
		gChangEdit = 0;
		//int regAddr = GetEditValue(IDC_EDIT_REG_ADDR, true);
		//if (DbsGetMemValue("regAddr") != regAddr) {
		//	gRegAddr = regAddr;
		//	DbsSetMemValue("regAddr", regAddr);
		//	SetEditHexValue(IDC_EDIT_REG_ADDR, gRegAddr, true);		// 写入HEX数值到CEdit
		//	ShowRegister();
		//}
	}
}

////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void CTabControl::ShowAccount(bool init) {
	char bytes[100];
	DbsGetMemText(bytes, sizeof(bytes), "an_0");
	CString name(bytes);
	DbsGetMemText(bytes, sizeof(bytes), "ap_0");
	CString psw(bytes);
	if (name != L"") {
		DbsGetMemText(bytes, sizeof(bytes), "an_1");
		CString devName(bytes);
		DbsGetMemText(bytes, sizeof(bytes), "gv_1");
		CString visit(bytes);
		((CEdit*)GetDlgItem(IDC_EDIT_DN))->SetWindowText(devName);
		((CEdit*)GetDlgItem(IDC_EDIT_VS))->SetWindowText(visit);
	}
	((CEdit*)GetDlgItem(IDC_EDIT_NAME))->SetWindowText(name);
	((CEdit*)GetDlgItem(IDC_EDIT_PSW))->SetWindowText(psw);
}
void CTabControl::ShowRegister() {
	char bytes[8192];
	DNT_INFO* info = DntGetInfo();							// 获取DNT_INFO*
	uint8_t* myReg = mTEST.MyReg;

	int offset = 0;
	CLOGD(TAG, "ShowRegister RegSize: %d", info->RegSize);
	for (int index = 0; index < info->RegSize; index++) {
		int position = index % 16;
		if (position == 0) {
			bytes[offset++] = '\r';
			bytes[offset++] = '\n';
			bytes[offset++] = TxtHexAscii((uint8_t)(index >> 8));
			bytes[offset++] = TxtHexAscii((uint8_t)index >> 4);
			bytes[offset++] = TxtHexAscii((uint8_t)index);
			bytes[offset++] = 'h';
			bytes[offset++] = ':';
			bytes[offset++] = ' ';
		}
		if (position == 4 || position == 8 || position == 12) {
			bytes[offset++] = ' ';
			bytes[offset++] = ' ';
			bytes[offset++] = ' ';
		}
		bytes[offset++] = ' ';
		bytes[offset++] = TxtHexAscii((uint8_t)myReg[index] >> 4);
		bytes[offset++] = TxtHexAscii((uint8_t)myReg[index]);
	}
	bytes[offset] = 0;
	CString text(bytes);
	((CEdit*)GetDlgItem(IDC_EDIT_REG))->SetWindowText(text);

	uint16_t crcs[1 + 8];
	int length = DiffBkTxMakeCrcs(crcs, myReg, info->RegSize);
	length = length / 2;
	if (!info->LoginOk) {
		offset = TxtFormat(bytes, 128, "dn及gv使用自己的账号名及密码，当前默认使用动态域名申请的账号，");
		offset += TxtFormat(bytes + offset, 128, "an及ap使用电器设备端的账号名及访问码，当前默认使用电器设备端申请的账号。\r\n");
	}else {
		offset = TxtFormat(bytes, 128, "寄存器长度为%u字节共%u块，", info->RegSize, length - 1);
		offset += TxtFormat(bytes + offset, 128, "当任意端改变数值，所有端都会同步地改变数值。使用sum16及每块crc检测变化\r\n");
		offset += TxtFormat(bytes + offset, 128, "\r\n[0]sum16:%04x [1-%u]crc:\r\n", crcs[0], length - 1);
		for (int index = 1; index < length; index++) {
			offset += TxtFormat(bytes + offset, 64, "%04x ", crcs[index]);
		}
	}
	CString string(bytes);
	((CStatic*)GetDlgItem(IDC_EDIT_TIPS))->SetWindowText(string);

	if (gChangEdit == 0) {									// 编辑框有更改时不能写编辑框
		ShowSlider(myReg[gRegAddr]);
	}
}
void CTabControl::ShowSlider(uint8_t value) {
	SetEditHexValue(IDC_EDIT_REG_DATA, value, false);		// 写入HEX数值到CEdit
	((CSliderCtrl*)GetDlgItem(IDC_SLIDER1))->SetPos(value);

}
int CTabControl::GetEditValue(int nID, bool isHex) {		// 获取CEdit输入的16进制或10进制数值
	CString text;
	((CStatic*)GetDlgItem(nID))->GetWindowText(text);
	char byte32[32];
	TxtUnicodeGbk(byte32, 32, (short*)text.AllocSysString());	// UNICODE转换到GBK
	return isHex ? TxtHexToValue(byte32, 0) : TxtToInt(byte32);		// 文字转换到数值
}
void CTabControl::SetEditHexValue(int nID, int value, bool three) {		// 写入HEX数值到CEdit
	CString text;
	text.Format(three ? L"%03x" : L"%02x", value);
	((CStatic*)GetDlgItem(nID))->SetWindowText(text);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////
void CTabControl::OnBnClickedButtonLogin() {
	char bytes[128];
	CString string;
	((CEdit*)GetDlgItem(IDC_EDIT_NAME))->GetWindowText(string);
	TxtUnicodeUtf8(bytes, sizeof(bytes), (short*)string.AllocSysString());	// UNICODE转换到GUTF8
	DbsSetMemText("an_0", bytes);
	((CEdit*)GetDlgItem(IDC_EDIT_PSW))->GetWindowText(string);
	TxtUnicodeUtf8(bytes, sizeof(bytes), (short*)string.AllocSysString());	// UNICODE转换到GUTF8
	DbsSetMemText("ap_0", bytes);
	((CEdit*)GetDlgItem(IDC_EDIT_DN))->GetWindowText(string);
	TxtUnicodeUtf8(bytes, sizeof(bytes), (short*)string.AllocSysString());	// UNICODE转换到GUTF8
	DbsSetMemText("an_1", bytes);
	((CEdit*)GetDlgItem(IDC_EDIT_VS))->GetWindowText(string);
	TxtUnicodeUtf8(bytes, sizeof(bytes), (short*)string.AllocSysString());	// UNICODE转换到GUTF8
	DbsSetMemText("gv_1", bytes);
	if (DbsGetMemText(bytes, sizeof(bytes), "an_0") > 0) {
		if (DbsGetMemText(bytes, sizeof(bytes), "ap_0") > 0) {
			if (DbsGetMemText(bytes, sizeof(bytes), "an_1") > 0) {
				if (DbsGetMemText(bytes, sizeof(bytes), "gv_1") > 0) {
					//DntSetState(STATE_LOGIN);			// 改变运行状态为登录服务器		
					DntSetIdleFlag(DNT_RB_LOGIN);		// 空闲回调 登录
					return;
				}
				::AfxMessageBox(L"请输入电器设备端访问码");
				return;
			}
			::AfxMessageBox(L"请输入电器设备端的账号名");
			return;
		}
		::AfxMessageBox(L"请输入控制端的账号密码");
		return;
	}
	::AfxMessageBox(L"请输入控制端的账号名");
}
void CTabControl::OnEnChangeEditReg() {
	gChangEdit = 1;
}

void CTabControl::OnNMCustomdrawSlider1(NMHDR* pNMHDR, LRESULT* pResult) {
	LPNMCUSTOMDRAW pNMCD = reinterpret_cast<LPNMCUSTOMDRAW>(pNMHDR);

	int position = ((CSliderCtrl*)GetDlgItem(IDC_SLIDER1))->GetPos();
	uint8_t* regs = mTEST.MyReg;
	//CLOGD(TAG, "Slider RegWrite %03x %02x %02x", gRegAddr, regs[gRegAddr], position);
	regs[gRegAddr] = (uint8_t)position;
	ShowSlider(regs[gRegAddr]);
	if (DntRegWrite()) {
		isChangReg = true;
		*pResult = 0;
		return;
	}
	*pResult = 0;
}
void CTabControl::OnBnClickedButtonRandom() {
	DNT_INFO* info = DntGetInfo();							// 获取DNT_INFO*
	if (info->LoginOk && info->RegSize != 0) {
		gRegAddr = rand() % info->RegSize;
		uint8_t value = (uint8_t)rand();
		DbsSetMemValue("regAddr", gRegAddr);
		ShowSlider(value);
		SetEditHexValue(IDC_EDIT_REG_ADDR, gRegAddr, true);		// 写入HEX数值到CEdit
		SetEditHexValue(IDC_EDIT_REG_DATA, value, false);	// 写入HEX数值到CEdit
		return;
	}
	::AfxMessageBox(L"出错");
}
void CTabControl::OnBnClickedButtonChange(){
	DNT_INFO* info = DntGetInfo();							// 获取DNT_INFO*
	int regAddr = GetEditValue(IDC_EDIT_REG_ADDR, true);
	if (regAddr < info->RegSize) {
		gRegAddr = regAddr;
		DbsSetMemValue("regAddr", regAddr);
	}

	int value = GetEditValue(IDC_EDIT_REG_DATA, true);			//  获取CEdit输入的16进制或10进制数值
	if (value <= 0x100) {
		SetEditHexValue(IDC_EDIT_REG_DATA, value, false);	// 写入HEX数值到CEdit
		uint8_t* regs = mTEST.MyReg;
		regs[gRegAddr] = (uint8_t)value;
		CLOGD(TAG, "改变寄存器0x%03x的值为0x%02x", gRegAddr, value);
		if (DntRegWrite()) {
			isChangReg = true;
			return;
		}
	}
	::AfxMessageBox(L"出错");
}

